﻿Ext.Container = Ext.extend(Ext.lib.Container, {

    //切换活动面板时的动画效果，有('fade', 'slide', 'flip', 'cube', 'pop', 'wipe')
    //只有在CardLayout布局下才有效
    cardSwitchAnimation: null,

    initComponent: function () {

        //如果设置了滚动
        if (this.scroll) {
            
            //专门放置表单类型子组件
            this.fields = new Ext.util.MixedCollection();

            //如果不是Blackberry平台
            if (!Ext.is.Blackberry) {
                this.fields.on({
                    add: this.onFieldAdd,//添加表单类型子组件时触发
                    remove: this.onFieldRemove,//移除表单类型子组件时触发
                    scope: this
                });
            }

            this.on({
                add: this.onItemAdd,//添加子组件的响应函数
                remove: this.onItemRemove,//移除子组件的响应函数
                scope: this
            });
        }


        Ext.Container.superclass.initComponent.apply(this, arguments);
    },

    //渲染后的方法
    afterRender: function () {

        //调用父类的同名方法
        Ext.Container.superclass.afterRender.apply(this, arguments);

        //如果滚动控件存在
        if (this.scroller) {
            if ((Ext.is.Android) && this.containsFormFields) {
                this.scroller.setUseCssTransform(false);
            }

            //给滚动控件注册响应函数
            this.scroller.on('scrollstart', this.onFieldScrollStart, this);
        }
    },

    //滚动开始时触发
    onFieldScrollStart: function () {
        var focusedField = this.focusedField;//获得焦点的表单类型子组件

        if (focusedField && Ext.is.iOS) {
            focusedField.blur();//表单类型子组件失去焦点
        }
    },

    //添加子组件的响应函数
    onItemAdd: function (me, item) {
        this.fields.addAll(Ext.ComponentQuery.query('[isField]', item));
    },

    //移除子组件的响应函数
    onItemRemove: function (me, item) {
        this.fields.removeAll(Ext.ComponentQuery.query('[isField]', item));
    },

    //添加表单类型子组件后的响应函数
    onFieldAdd: function (key, field) {
        this.handleFieldEventListener(true, field);
    },

    //移除表单类型子组件后的响应函数
    onFieldRemove: function (key, field) {
        this.handleFieldEventListener(false, field);
    },

    //给表单类型子组件注册或注销事件响应函数，表单类型子组件的获取或失去焦点事件将影响滚动
    handleFieldEventListener: function (isAdding, item) {
        if (!this.fieldEventWrap)
            this.fieldEventWrap = {};

        if (['textfield', 'passwordfield', 'emailfield',
             'textareafield', 'searchfield', 'urlfield',
             'numberfield', 'spinnerfield'].indexOf(item.xtype) !== -1) {

            //如果是注册，构造包含事件响应函数的对象
            if (isAdding) {
                this.fieldEventWrap[item.id] = {
                    beforefocus: function (e) { this.onFieldBeforeFocus(item, e); },
                    focus: function (e) { this.onFieldFocus(item, e); },
                    blur: function (e) { this.onFieldBlur(item, e); },
                    keyup: function (e) { this.onFieldKeyUp(item, e); },
                    scope: this
                };

                this.containsFormFields = true;
            }

            //根据构造的包含事件响应函数的对象注册或注销响应函数
            item[isAdding ? 'on' : 'un'](this.fieldEventWrap[item.id]);

            //如果注销响应函数，则注销后连包含事件响应函数的对象一起销毁
            if (!isAdding) {
                delete this.fieldEventWrap[item.id];
            }
        }
    },

    onFieldKeyUp: function (field, e) {
        if (Ext.is.iOS || Ext.is.Desktop) {
            this.resetLastWindowScroll();
        }
    },

    onFieldBeforeFocus: function (field, e) {
        this.focusingField = field;
    },

    getLastWindowScroll: function () {
        if (!this.lastWindowScroll) {
            this.resetLastWindowScroll();
        }

        return { x: this.lastWindowScroll.x, y: this.lastWindowScroll.y };
    },

    resetLastWindowScroll: function () {
        this.lastWindowScroll = {
            x: window.pageXOffset,
            y: window.pageYOffset
        };
    },

    adjustScroller: function (offset) {
        var scroller = this.getClosestScroller(),
            windowScroll = this.getLastWindowScroll();

        scroller.setOffset(offset);


        if (Ext.is.iOS) {
            window.scrollTo(windowScroll.x, windowScroll.y);
        }

        this.resetLastWindowScroll();
    },

    onFieldFocus: function (field, e) {
        if (!Ext.is.iOS && !Ext.is.Desktop) {
            var dom = field.fieldEl.dom;

            if (dom.scrollIntoViewIfNeeded) {
                dom.scrollIntoViewIfNeeded(true);
            }
        }
        else {
            var scroller = this.getClosestScroller(),
                containerRegion = Ext.util.Region.from(scroller.containerBox),
                fieldRegion = field.fieldEl.getPageBox(true);


            if (this.focusingField == field || !Ext.is.iOS) {
                if (Ext.is.iOS && window.pageYOffset == 0) {
                    window.scrollTo(0, 0);
                }

                var adjustment = new Ext.util.Offset();

                if (fieldRegion.left < containerRegion.left) {
                    adjustment.x = containerRegion.left - fieldRegion.left;
                }

                if (fieldRegion.top < containerRegion.top) {
                    adjustment.y = containerRegion.top - fieldRegion.top;
                }

                if (!adjustment.isZero()) {
                    var windowScroll = this.getLastWindowScroll();

                    scroller.scrollBy(adjustment);

                    if (Ext.is.iOS) {
                        window.scrollTo(windowScroll.x, windowScroll.y);
                    }

                    this.resetLastWindowScroll();
                }
            }

            else {
                if (this.lastFocusedField) {
                    var deltaY = fieldRegion.top - this.lastFocusedField.fieldEl.getY(),
                        offsetY = scroller.offset.y - deltaY,
                        selfHandling = false;

                    if (!containerRegion.contains(fieldRegion) &&
                        (offsetY != 0 || (offsetY == 0 && scroller.offset.y != 0))) {
                        selfHandling = true;
                    }

                    if (offsetY > 0) {
                        offsetY = 0;
                    }

                    if (selfHandling) {
                        this.adjustScroller(new Ext.util.Offset(
                            scroller.offset.x, offsetY
                        ));
                    }
                }
            }

            this.resetLastWindowScroll();
        }

        this.lastFocusedField = field;
        this.focusedField = field;
        this.focusingField = null;
    },

    getClosestScroller: function () {
        if (!this.closestScroller) {
            this.closestScroller = this.scroller || this.el.getScrollParent();
        }

        return this.closestScroller;
    },

    onFieldBlur: function (field, e) {
        if (this.focusingField == field) {
            this.focusingField = null;
        }

        if (this.focusedField == field) {
            this.focusedField = null;
        }
    },

    //布局后的工作
    afterLayout: function (layout) {
        if (this.floating && this.centered) {
            this.setCentered(true, true);
        }

        //如果有滚动控件，进行滚动控件的一些单独处理
        if (this.scroller) {
            this.scroller.updateBoundary();
        }
        Ext.Container.superclass.afterLayout.call(this, layout);
    },

    //获取当前活动子组件
    getActiveItem: function () {
        if (this.layout && this.layout.type == 'card') {
            return this.layout.activeItem;
        }
        else {
            return null;
        }
    },

    //设置当前活动子组件
    setActiveItem: function (card, animation) {
        this.layout.setActiveItem(card, animation);
        return this;
    },



    onBeforeCardSwitch: function (newCard, oldCard, newIndex, animated) {
        return this.fireEvent('beforecardswitch', this, newCard, oldCard, newIndex, animated);
    },


    onCardSwitch: function (newCard, oldCard, newIndex, animated) {
        return this.fireEvent('cardswitch', this, newCard, oldCard, newIndex, animated);
    },

    //禁用当前容器
    disable: function () {
        Ext.Container.superclass.disable.call(this);
        this.el.mask(null, 'x-mask-gray');
    },

    //启用当前容器
    enable: function () {
        Ext.Container.superclass.enable.call(this);
        this.el.unmask();
    }
});

Ext.reg('container', Ext.Container);
